package com.example.learningspringboot.email.service;

import com.example.learningspringboot.email.utils.EmailUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

/**
 * @Author: Shu Ting
 * @CreateTime: 2024-08-22 23:45
 * @Description: Java 发送邮件测试
 * @Version: 1.0
 */

@Slf4j
@Service
public class EmailService {

    /**
     * 在Bean的依赖注入上使用的构造函数方式,依赖注入的Bean对象使用final来修饰;
     *下面是这样做的原因:
     * 1.不可变性 (Immutability)
     * 优势:一旦在构造函数中赋值，就不能再被修改,防止在类的其他方法中意外重新赋值,确保依赖关系在整个对象生命周期中保持一致
     * 2.线程安全，具体需要DeepSeek
     * 3.明确的设计意图
     * 4.编译时检查,如果没有初始化final字段，编译器会报错,如果忘记这行赋值，编译错误：variable productRepository might not have been initialized
     * 5.与Spring框架的协作
     * 6.防止NPE（空指针异常），我们可以在构造函数赋值的时候进行null检查
     * 7.函数式编程风格
     * 8.与记录类（Record）的兼容性
     * 总结:
     * 使用final修饰注入的bean是Spring开发中的最佳实践，因为它：
     * ✅ 增强安全性：防止意外修改依赖
     * ✅ 提高可读性：明确表达设计意图
     * ✅ 支持线程安全：天然的不可变对象
     * ✅ 便于测试：依赖关系明确且稳定
     * ✅ 编译时保障：编译器帮助检查初始化
     * ✅ 符合函数式编程原则：鼓励不可变性
     */
    private final EmailUtil emailUtil;

    /**
     * 这里我们使用的构造函数进行依赖注入
     * 在单一构造函数下可省略
     */
    @Autowired
    public EmailService(EmailUtil emailUtil) {
        this.emailUtil = emailUtil;
    }

    public void sendMail(String from,String to,String cc,String subject,String text){
        SimpleMailMessage smm = new SimpleMailMessage();
        //发送者
        smm.setFrom(from);
        //收件人
        smm.setTo(to);
        //抄送人
        smm.setCc(cc);
        //邮件主题
        smm.setSubject(subject);
        //邮件内容
        smm.setText(text);
        //发送邮件
        boolean sender = emailUtil.sender(smm);
        log.info("发送状态: {}", sender);
    }
}
